home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Text / print / HPDJ870Src.lha / compression.c next >
C/C++ Source or Header  |  2004-05-15  |  6KB  |  232 lines

  1. /*
  2.  * $Id: compression.c 44.1 1999/09/02 11:08:00 olsen Exp olsen $
  3.  *
  4.  * :ts=4
  5.  *
  6.  * COPYRIGHT:
  7.  *
  8.  *   Unless otherwise noted, all files are Copyright (c) 1999 Amiga, Inc.
  9.  *   All rights reserved.
  10.  *
  11.  * DISCLAIMER:
  12.  *
  13.  *   This software is provided "as is". No representations or warranties
  14.  *   are made with respect to the accuracy, reliability, performance,
  15.  *   currentness, or operation of this software, and all use is at your
  16.  *   own risk. Neither Amiga nor the authors assume any responsibility
  17.  *   or liability whatsoever with respect to your use of this software.
  18.  *
  19.  */
  20.  
  21. #include "global.h"
  22.  
  23. /*****************************************************************************/
  24.  
  25. LONG StripWhiteSpace(UBYTE * source,LONG size)
  26. {
  27.     LONG i;
  28.  
  29.     /* Optimization: strip all trailing zero bytes. */
  30.     for(i = size ; i > 0 ; i--)
  31.     {
  32.         if(source[i-1] != 0)
  33.         {
  34.             size = i;
  35.             break;
  36.         }
  37.     }
  38.  
  39.     return(size);
  40. }
  41.  
  42. /*****************************************************************************/
  43.  
  44. /* PCL compression method #2, also known as "TIFF packbits" or ByteRun1. */
  45. LONG CompressMethod2(
  46.     UBYTE * src,
  47.     UBYTE * dest,
  48.     LONG count)
  49. {
  50.     UBYTE *    last = dest + count;
  51.  
  52.     UBYTE * outptr;
  53.     UBYTE * inptr;
  54.     UBYTE * saveptr;
  55.  
  56.     UBYTE    data;        /* data byte */
  57.     UBYTE    lastbyte;    /* last byte */
  58.     LONG    repcount;    /* repeat count */
  59.     LONG    litcount;    /* literal count */
  60.  
  61.     inptr = src;
  62.     outptr = dest;
  63.  
  64.     /* Start loop through data. Check for possible repeat at beginning. */
  65.     while(count > 0)
  66.     {
  67.         /* get value to work with */
  68.         data = (*inptr++);
  69.         count--;
  70.  
  71.         /* no repeat count yet */
  72.         repcount = 0;
  73.  
  74.         /* Check for repeat, since we are not in the middle
  75.          * of a literal run, it does not have to be more than
  76.          * two bytes of similar data.
  77.          */
  78.         while(count > 0 && (*inptr) == data)
  79.         {
  80.             repcount++;
  81.             inptr++;
  82.  
  83.             count--;
  84.         }
  85.  
  86.         /* Now, if we are out of data (count == 0), then
  87.          * if the repeated byte was zero, then ignore it
  88.          * completely (don't bother outputing the trailing zeros).
  89.          */
  90.         if(count == 0 && data == 0)
  91.             break; /* done */
  92.  
  93.         /* If there was a repeat (repcount > 0), then we
  94.          * can output the command here, otherwise, we
  95.          * need to go into literal run mode.
  96.          *
  97.          * Note:  This is a while loop because the repeat count
  98.          * may actually be greater than 127.
  99.          */
  100.  
  101.         if(repcount >= 1) /* repeat mode */
  102.         {
  103.             while(repcount > 127)
  104.             {
  105.                 if(outptr + 2 > last)
  106.                     return(-1);
  107.  
  108.                 (*outptr++) = 129;    /* count 127 */
  109.                 (*outptr++) = data;    /* value */
  110.                 repcount -= 128;    /* offset */
  111.             }
  112.  
  113.             if(repcount > 0)
  114.             {
  115.                 if(outptr + 2 > last)
  116.                     return(-1);
  117.  
  118.                 (*outptr++) = 256 - repcount;    /* count */
  119.                 (*outptr++) = data;        /* value */
  120.  
  121.                 /* Now pop to the top of the loop 
  122.                  * looking for more repeat counts.
  123.                  */
  124.  
  125.                 continue; /* top of loop */
  126.             }
  127.  
  128.             /* Special case.  If we have arrived at this point,
  129.              * then repcount is now equal to 0.  This means
  130.              * that when we entered this section, repcount
  131.              * was a multiple of 128 (i.e. 128 :-).
  132.              *
  133.              * This means that there were 129 identical bytes,
  134.              * so the output does a replicate of 127 which
  135.              * gives 128 bytes, and we now have one byte left
  136.              * over which should NOT be output as a repeat
  137.              * run, rather it should be merged into the following
  138.              * literal run (if it exists).
  139.              *
  140.              * So, we will simply fall thru to the next section
  141.              * of code which assumes that we are working on 
  142.              * a literal run.
  143.              */
  144.         }
  145.  
  146.         /* Literal run.  At this point, the current data byte
  147.          * does NOT match the following byte.  We will transfer
  148.          * these non-identical bytes until:
  149.          *
  150.          *      1)  we run out of input data (count == 0).
  151.          *      2)  we run out of room in this output block (128)
  152.          *      3)  we come across a value which occurs at least
  153.          *          three times in a row.  A value occuring only
  154.          *          twice in a row does NOT justify dropping
  155.          *          out of a literal run.
  156.          *
  157.          * Special case:  If we run out of room in the output block
  158.          * (which is 128 bytes), the last two values are the same,
  159.          * AND there is more input, it makes sense to restart
  160.          * the repeat detector in case the following bytes are
  161.          * repeats of the two.  A simple check of the following
  162.          * byte will determine this.
  163.          * (This case falls out with the test for triples below).
  164.          *
  165.          * Special case:  If we run out of room in the output block
  166.          * (which is 128 bytes), the last value is the same as
  167.          * the next one on the input, then it is better to let
  168.          * that byte be used in a possible replicate run following
  169.          * the literal run.  If the last byte matches ONLY the
  170.          * following byte, (and not the one after that, it is
  171.          * a wash, but for best results, we will test the
  172.          * following two bytes.
  173.          */
  174.  
  175.         litcount = 0;
  176.         saveptr = outptr++;    /* save location of the command byte */
  177.  
  178.         if(outptr + 1 > last)
  179.             return(-1);
  180.  
  181.         (*outptr++) = data;    /* save the first byte. */
  182.  
  183.         lastbyte = data;    /* remember for testing */
  184.  
  185.         while(count > 0 && litcount < 127)
  186.         {
  187.             data = (*inptr++);
  188.             count--;
  189.             litcount++;
  190.  
  191.             if(outptr + 1 > last)
  192.                 return(-1);
  193.  
  194.             (*outptr++) = data;
  195.  
  196.             /* Test to see if this byte matched the last one.
  197.              * If so, check the next one for a triple.
  198.              */
  199.             if(lastbyte == data && count > 0 && (*inptr) == data)
  200.             {
  201.                 /* We have a triple, adjust accordingly.
  202.                  * Add two bytes back onto the input.
  203.                  */
  204.  
  205.                 count += 2;
  206.                 inptr -= 2;
  207.                 outptr -= 2;
  208.                 litcount -= 2;
  209.  
  210.                 break; /* out of loop */
  211.             }
  212.  
  213.             lastbyte = data; /* save data byte */
  214.         }
  215.  
  216.         /* Check the special case number 2 above. */
  217.         if(litcount == 127 && count > 1 && data == (*inptr) && data == inptr[1])
  218.         {
  219.             /*  Restore the last byte to the input stream */
  220.             count += 1;
  221.             inptr -= 1;
  222.             outptr -= 1;
  223.             litcount -= 1;
  224.         }
  225.  
  226.         /* Save the literal run count. */
  227.         (*saveptr) = litcount;
  228.     }
  229.  
  230.     return(outptr - dest);
  231. }
  232.